import * as gbk from './printUtil-GBK'
const uniApi: any = uni
/**
 * @export
 * @param {string} name uniapp api的名称 ，如 uniAsyncPromise("getSystemInfo",options)
 * @param {object} options 除了success 和 fail 的其他参数
 * @returns
 */
export function uniAsyncPromise(name: string, options?: any): Promise<any> {
  return new Promise((resolve, reject) => {
    uniApi[name]({
      ...options,
      success: function (res: any) {
        resolve(res)
      },
      fail: function (res: any) {
        reject(res)
      },
    })
  })
}

interface PrintElement {
  printElementType: {
    type: string
  }
  options: {
    left: number
    top: number
    width: number
    height: number
    fontSize?: number
    field?: string
    title?: string
    hideTitle?: boolean
    textAlign?: string
    textContentVerticalAlign?: string
    fontWeight?: number
    lineHeight?: number
    textType?: string
  }
}

export function changeJson(panels: any, printData: any) {
	
  console.log(typeof panels !== 'object');
  console.log(!panels.printElements?.length);
	
  if (typeof panels !== 'object' || !panels.printElements?.length) {
    throw new Error('Invalid panels')
  }

  const formatDateTime = () => {
    const now = new Date();
    const yy = String(now.getFullYear()).slice(-2);
    const mm = String(now.getMonth() + 1).padStart(2, '0');
    const dd = String(now.getDate()).padStart(2, '0');
    const hh = String(now.getHours()).padStart(2, '0');
    const min = String(now.getMinutes()).padStart(2, '0');
    const ss = String(now.getSeconds()).padStart(2, '0');
    return `${yy}-${mm}-${dd} ${hh}:${min}:${ss}`;
  };

  printData = {
    ...printData,
    printTime: formatDateTime(),
  }

  let mm = {
    toDot: (val: number) => {
      return 8 * val
    },
  }

  let pt = {
    toMm: (val: number) => {
      return val * 0.36
    },
    toDot: (val: number) => {
      return mm.toDot(pt.toMm(val))
    },
  }

  panels.printElements.forEach((el: PrintElement) => {
    if (el.printElementType.type === 'text') {
      switch (el.options.textType) {
        case 'qrcode':
        case 'barcode':
          el.printElementType.type = el.options.textType
          break
      }
    }
  })

  let pageWidth = mm.toDot(panels.width)
  let pageHeight = mm.toDot(panels.height)
  let strCmd = ''
  strCmd += CreatCPCLPage(pageWidth, pageHeight, 1, 0)

  panels.printElements.forEach((el: PrintElement) => {
    let {
      left,
      top,
      width,
      height,
      fontSize,
      field,
      title,
      hideTitle,
      textAlign,
      textContentVerticalAlign,
      fontWeight,
      lineHeight,
    }: any = el.options

    left = pt.toDot(left)
    top = pt.toDot(top)
    width = pt.toDot(width)
    height = pt.toDot(height)
    lineHeight = pt.toDot(lineHeight || fontSize || 9)

    let setmag = Math.ceil(pt.toDot(fontSize || 9) / 18)
    if (setmag > 16) {
      setmag = 16
    }
    switch (el.printElementType.type) {
      case 'text':
        let obj = {
          right: addCPCLLocation(1),
          center: addCPCLLocation(2),
        } as any
        setmag && (strCmd += addCPCLSETMAG(setmag, setmag))
          ;['right', 'center'].includes(textAlign) &&
            (strCmd += obj[textAlign] || '')
        fontWeight && (strCmd += addCPCLBold(fontWeight))
        strCmd += addCPCLText(
          left,
          top,
          '55',
          0,
          0,
          `${hideTitle ? '' : title || ''}${!hideTitle && field ? ':' : ''}${printData[field] || ''
          }`
        )
          ;['right', 'center'].includes(textAlign) &&
            (strCmd += addCPCLLocation())
        fontWeight && (strCmd += addCPCLBold())
        break
      case 'barcode':
        strCmd += addCPCLBarCode(
          left,
          top,
          '128',
          height,
          0,
          1,
          1,
          printData[field] || title
        )
        break
      case 'qrcode':
        strCmd += addCPCLQRCode(
          left,
          top,
          'M',
          2,
          7,
          printData[field] || title
        )
        break
      case 'longText':
        let content = ''
          ; (() => {
            content = (printData[field] || title)
              .split(new RegExp(`(.{${Math.floor(width / Math.ceil(setmag * 16))}})`))
              .filter((val: any) => val)
              .join('\n')
          })()
        setmag && (strCmd += addCPCLSETMAG(setmag, setmag))
        fontWeight && (strCmd += addCPCLBold(fontWeight))
        strCmd += addCPCLMultLine(left, top, lineHeight, '55', 0, 0, content)
        fontWeight && (strCmd += addCPCLBold())
        break
    }
  })
  strCmd += addCPCLPrint()
  console.log(strCmd)

  let buffer = gbk.strToGBKByte(strCmd)
  return buffer
}


//uniapp 小程序向蓝牙打印机发送数据进行打印的坑：
//小程序api向蓝牙打印机发送数据打印，发送的任何内容都应该要转成二进制数据，而且蓝牙打印的文本编码是GBK的，发送中文需转成GBK编码再转成二进制数据发送
//发送打印机指令也要转成二进制数据发送
//蓝牙打印机一次接收的二级制数据有限制，不同的系统不同的蓝牙设备限制可能不同，uniapp 建议一次20个字节，需做递归分包发送
//发送完要打印的内容后，一定要发送一个打印的指令才能顺利打印 （有些指令就不需要）

//一、初始化蓝牙、开始检索蓝牙设备
export function openBlue() {
  return uniAsyncPromise('openBluetoothAdapter').then(res => {
    console.log('初始化蓝牙成功', res)
  })
}

export function startBluetoothDevicesDiscovery() {
  uniAsyncPromise('startBluetoothDevicesDiscovery').then(res => {
    console.log('正在搜寻蓝牙设备', res)
  })
}
//二、
/**
 *
 *
 * @export
 * @param {function} getDevices uni.getBluetoothDevices的监听回调函数
 */
export function onfindBlueDevices(getDevices: any) {
  //监听寻找到新设备的事件
  uni.onBluetoothDeviceFound(function (devices) {
    //获取在蓝牙模块生效期间所有已发现的蓝牙设备
    uniAsyncPromise('getBluetoothDevices').then(res => {
      getDevices && getDevices(res.devices)
    })
  })
}

/**
 * @export
 * @param {function} stopBlueDevicesDiscovery 关闭蓝牙扫描
 */
export function stopBlueDevicesDiscovery() {
  //监听寻找到新设备的事件
  console.log('停止蓝牙扫描')
  return uniAsyncPromise('stopBluetoothDevicesDiscovery').then(res => {
    console.log('停止搜寻蓝牙设备', res)
  })
}

//三、连接蓝牙设备
/**
 * @export
 * @param {function} createBLEConnection
 * @param {number} deviceId 蓝牙设备id
 */
export function createBLEConnection(deviceId: number, sucess: any, fail: any) {
  //连接蓝牙设备
  console.log('连接蓝牙设备', deviceId)
  uniAsyncPromise('createBLEConnection', { deviceId })
    .then(res => {
      //连接成功可选择停止搜索蓝牙
      //stopBlueDevicesDiscovery();
      console.log('连接成功')
      sucess &&
        sucess({
          res: res,
        })
    })
    .catch(res => {
      console.log('连接设备异常', res)
      fail &&
        fail({
          res: res,
        })
    })
  /*.finally(res=>{
             console.log('连接成功');
             sucess && sucess({
                 res: res,
             });
         });*/
}

export function closeBLEConnection(deviceId: number) {
  console.log('断开蓝牙设备', deviceId)
  uniAsyncPromise('closeBLEConnection', { deviceId })
    .then(res => {
      console.log('BLEDisconnect complete', res)
    })
    .catch(res => {
      console.log('断开设备异常', res)
    })
  /*.finally(res=>{
             console.log('BLEDisconnect complete', res);            
         });  */
}

//四、连接成功后， 获取蓝牙设备的service服务
// uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})
export function getBLEDeviceServices(deviceId: number, success: any, fail: any, retryCount = 0) {
  console.log('获取ServiceId', deviceId)
  const maxRetries = 3;
  const retryDelay = 1000; // 1秒延迟
  
  uniAsyncPromise('getBLEDeviceServices', { deviceId })
    .then(res => {
      console.log('服务', res.services)
      
      // 检查服务是否为空
      if (!res.services || res.services.length === 0) {
        if (retryCount < maxRetries) {
          console.log(`服务为空，${retryCount + 1}秒后重试...`)
          setTimeout(() => {
            getBLEDeviceServices(deviceId, success, fail, retryCount + 1);
          }, retryDelay);
          return;
        }
      }
      
      success &&
        success({
          serviceId: res.services,
        })
    })
    .catch(res => {
      //getBLEDeviceServices(deviceId, success, fail);
      console.log('获取ServiceId异常', res)
      
      // 出错时也尝试重试
      if (retryCount < maxRetries) {
        console.log(`获取服务异常，${retryCount + 1}秒后重试...`)
        setTimeout(() => {
          getBLEDeviceServices(deviceId, success, fail, retryCount + 1);
        }, retryDelay);
        return;
      }
      
      fail &&
        fail({
          res: res,
        })
    })
}

//五、获取的service服务可能有多个，递归获取特征值（最后要用的是能读，能写，能监听的那个值的uuid作为特征值id）
/**
 *
 *
 * @export
 * @param {number} deviceId 蓝牙设备id
 * @param {array} services uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})获取的res.services
 * @param {function} success 成功取得有用特征值uuid的回调函数
 */
export function getDeviceCharacteristics(deviceId: number, services: any, success: any, fail: any) {
  //services = services.slice(0);
  console.log('获取Characteristics', deviceId, services)
  if (services.length) {
    const serviceId = services.shift().uuid
    console.log('ServceID ', serviceId)
    uniAsyncPromise('getBLEDeviceCharacteristics', {
      deviceId,
      serviceId,
    })
      .then(res => {
        console.log('getBLEDeviceCharacteristics', deviceId, serviceId, res)
        let finished = false
        let write = false
        let notify = false
        let indicate = false
        var readId
        var writeId
        //有斑马品牌的一款打印机中res.characteristics的所有uuid都是相同的，找所有的properties存在(notify || indicate) && write这种情况就说明这个uuid是可用的（不确保所有的打印机都能用这种方式取得uuid,在主要测试得凯盛诺打印机res.characteristic只有一个uuid,所以也能用这个方式）
        for (var i = 0; i < res.characteristics.length; i++) {
          if (!notify) {
            notify = res.characteristics[i].properties.notify
            if (notify) readId = res.characteristics[i].uuid
          }
          if (!indicate) {
            indicate = res.characteristics[i].properties.indicate
            if (indicate) readId = res.characteristics[i].uuid
          }
          if (!write) {
            write = res.characteristics[i].properties.write
            writeId = res.characteristics[i].uuid
          }
          if ((notify || indicate) && write) {
            /* 获取蓝牙特征值uuid */
            success &&
              success({
                serviceId,
                writeId: writeId,
                readId: readId,
              })
            finished = true
            break
          }
        }

        if (!finished) {
          getDeviceCharacteristics(deviceId, services, success, fail)
        }
      })
      .catch(res => {
        getDeviceCharacteristics(deviceId, services, success, fail)
      })
  } else {
    fail && fail()
  }
}

//六、启动notify 蓝牙监听功能 然后使用 uni.onBLECharacteristicValueChange用来监听蓝牙设备传递数据
/**
 *
 *
 * @export
 * @param {object} options
 * {
            deviceId,//蓝牙设备id
            serviceId,//服务id
            characteristicId,//可用特征值uuid
    }
 * @param {function} onChange 监听蓝牙设备传递数据回调函数
 */
export function onGetBLECharacteristicValueChange(
  options: any,
  onChange = function () { }
) {
  console.log('deviceId ', options.deviceId)
  console.log('serviceId ', options.serviceId)
  console.log('characteristicId ', options.characteristicId)
  uniAsyncPromise('notifyBLECharacteristicValueChange', {
    state: true,
    ...options,
  }).then(res => {
    console.log('onBLECharacteristicValueChange ')
    uni.onBLECharacteristicValueChange(onChange)
  })
}

//七、发送数据(递归分包发送)
/**
 * @description: 打印事件，数据包不分段
 * @param {*} options
 * @return {*}
 */
export function printToDevice(options: any) {
  // 使用队列进行打印，解决并非问题
  runner.add((done: any) => {
    sendDataToDevice(options).finally(() => {
      done()
    })
  })
}
/**
 * @description: 打印事件，数据包分段
 * @export
 * @param {object} options
 * {
            deviceId,
            serviceId,
            characteristicId,
      value [ArrayBuffer],
      lasterSuccess,
            onceLength
    }
 */
export function sendDataToDevice(options: any) {
  return new Promise((resolve, reject) => {
    let byteLength = options.value.byteLength
    //这里默认一次20个字节发送
    const speed = options.onceLength || 20;
    console.log('准备发送数据, 总长度:', byteLength, '每次发送:', speed);
    
    if (byteLength > 0) {
      const sendLength = byteLength > speed ? speed : byteLength;
      const sendValue = options.value.slice(0, sendLength);
      console.log('发送数据片段, 长度:', sendValue.byteLength);
      
      // 每次发送都回调进度
      if (options.progressCallback && typeof options.progressCallback === 'function') {
        options.progressCallback(sendLength);
      }
      
      uniAsyncPromise('writeBLECharacteristicValue', {
        ...options,
        value: sendValue,
      })
        .then(res => {
          console.log('片段发送成功:', res);
          options.success && options.success(res);
          
          if (byteLength > speed) {
            console.log('还有更多数据, 继续发送...');
            setTimeout(() => {
              resolve(
                sendDataToDevice({
                  ...options,
                  value: options.value.slice(speed, byteLength),
                })
              )
            }, 100); // 增加100ms延迟，给设备处理时间
          } else {
            console.log('所有数据发送完成');
            options.lasterSuccess && options.lasterSuccess();
            resolve(null);
          }
        })
        .catch(res => {
          console.error('发送数据片段失败:', res);
          options.fail && options.fail(res);
          reject(res);
        });
    } else {
      console.log('没有数据可发送');
      resolve(null);
    }
  });
}
export function charToArrayBuffer(str: any) {
  var out = new ArrayBuffer(str.length)
  var uint8 = new Uint8Array(out)
  var strs = str.split('')
  for (var i = 0; i < strs.length; i++) {
    uint8[i] = strs[i].charCodeAt()
  }
  return uint8
}
export function charToArray(str: any) {
  var arr = []
  var strs = str.split('')
  for (var i = 0; i < strs.length; i++) {
    arr[i] = strs[i].charCodeAt()
  }
  return arr
}
//打印二维码
/**
 *
 *
 * @export
 * @param {object} options
 * {
            deviceId,
            serviceId,
            characteristicId,
            value,//ArrayBuffer:二维码的数据
    }
 */
export function printQR(options: any) {
  //打印二维码的十进制指令data：
  let data = [29, 107, 97, 7, 4, options.value.byteLength, 0]
  sendDataToDevice({
    ...options,
    value: new Uint8Array(data).buffer,
    lasterSuccess: () => {
      //指令发送成功后，发送二维码的数据
      sendDataToDevice(options)
    },
  })
}

function grayPixle(pix: any) {
  return pix[0] * 0.299 + pix[1] * 0.587 + pix[2] * 0.114
}

export function overwriteImageData(data: any) {
  let sendWidth = data.width,
    sendHeight = data.height
  const threshold = data.threshold || 180
  let sendImageData: any = new ArrayBuffer((sendWidth * sendHeight) / 8)
  sendImageData = new Uint8Array(sendImageData)
  let pix = data.imageData
  const part = []
  let index = 0
  for (let i = 0; i < pix.length; i += 32) {
    //横向每8个像素点组成一个字节（8位二进制数）。
    for (let k = 0; k < 8; k++) {
      const grayPixle1 = grayPixle(pix.slice(i + k * 4, i + k * 4 + (4 - 1)))
      //阈值调整
      if (grayPixle1 > threshold) {
        //灰度值大于threshold位   白色 为第k位0不打印
        part[k] = 0
      } else {
        part[k] = 1
      }
    }
    let temp = 0
    for (let a = 0; a < part.length; a++) {
      temp += part[a] * Math.pow(2, part.length - 1 - a)
    }
    //开始不明白以下算法什么意思，了解了字节才知道，一个字节是8位的二进制数，part这个数组存的0和1就是二进制的0和1，传输到打印的位图数据的一个字节是0-255之间的十进制数，以下是用权相加法转十进制数，理解了这个就用上面的for循环替代了
    // const temp =
    //     part[0] * 128 +
    //     part[1] * 64 +
    //     part[2] * 32 +
    //     part[3] * 16 +
    //     part[4] * 8 +
    //     part[5] * 4 +
    //     part[6] * 2 +
    //     part[7] * 1;
    sendImageData[index++] = temp
  }
  return {
    array: Array.from(sendImageData),
    width: sendWidth / 8,
    height: sendHeight,
  }
}
/**
 * printImage
 * @param {object} opt
 * {
            deviceId,//蓝牙设备id
            serviceId,//服务id
            characteristicId,//可用特征值uuid
            lasterSuccess , //最后完成的回调
    }
 */
export function printImage(opt: any = {}, imageInfo: any = {}) {
  let arr = imageInfo.array,
    width = imageInfo.width
  const writeArray = []
  const xl = width % 256
  const xh = width / 256
  //分行发送图片数据,用的十进制指令
  const command = [29, 118, 48, 0, xl, xh, 1, 0] //1D 76 30 00 w h
  const enter = [13, 10]
  for (let i = 0; i < arr.length / width; i++) {
    const subArr = arr.slice(i * width, i * width + width)
    const tempArr = command.concat(subArr)
    writeArray.push(new Uint8Array(tempArr))
  }
  writeArray.push(new Uint8Array(enter))
  //console.log(writeArray);
  const print = (options: any, writeArray: any) => {
    if (writeArray.length) {
      console.log('send')
      sendDataToDevice({
        ...options,
        value: writeArray.shift().buffer,
        lasterSuccess: () => {
          if (writeArray.length) {
            print(options, writeArray)
          } else {
            options.lasterSuccess && options.lasterSuccess()
          }
        },
      })
    }
  }
  console.log('start print')
  print(opt, writeArray)
}

/* 16hex insert 0 */
function Hex2Str(num: any) {
  if (num.toString(16).length < 2) return '0' + num.toString(16)
  else return num.toString(16)
}
/*****CPCL指令接口****/

/**
 * 配置项如下
 *
 * width: 标签纸的宽度，单位像素點
 * height: 标签纸的高度，单位像素點
 * 8像素=1mm
 * printNum: 打印张数，默认为1
 * rotation：页面整体旋转 1-90度 2-180度 3-270度 其他-不旋转
 */
export function CreatCPCLPage(width: any, height: any, printNum: any, rotation = 0) {
  // 标签纸模式下使用特殊初始化指令
  var strCmd = '! 0 200 200 ' + height + ' ' + printNum + '\n'
  // 添加COUNTRY命令设置文字编码
  strCmd += 'COUNTRY CHINA\n'
  // 添加纸张宽度设置
  strCmd += 'PAGE-WIDTH ' + width + '\n'
  // 使用GAP-SENSE确保标签之间的正确定位
  strCmd += 'GAP-SENSE\n'
  // 设置旋转
  if (rotation == 1) strCmd += 'ZPROTATE90\n'
  else if (rotation == 2) strCmd += 'ZPROTATE180\n'
  else if (rotation == 3) strCmd += 'ZPROTATE270\n'
  else strCmd += 'ZPROTATE0\n'
  return strCmd
}

/**
 * 打印文字
 * x: 文字方块左上角X座标，单位dot
 * y: 文字方块左上角Y座标，单位dot
 * fontName,fontSize: 字体，取值： 參考文檔
 * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
 * content: 文字内容
 */
export function addCPCLText(x: number, y: number, fontName: string, fontSize: number, rotation: number, content: string): string {
  //console.log(fontName,fontSize,rotation, content);
  var strCmd = ''
  if (rotation == 1) {
    strCmd += 'T90 '
  }
  if (rotation == 2) {
    strCmd += 'T180 '
  }
  if (rotation == 3) {
    strCmd += 'T270 '
  } else {
    strCmd += 'T '
  }
  strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n'
  return strCmd
}

/**
 * 打印多行
 * x: 文字方块左上角X座标，单位dot
 * y: 文字方块左上角Y座标，单位dot
 * h: 每行文字的高度，单位dot
 * fontName,fontSize: 字体，取值： 參考文檔
 * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
 * content: 文字内容
 */
export function addCPCLMultLine(
  x: number,
  y: number,
  h: number,
  fontName: string,
  fontSize: number,
  rotation: number,
  content: string
): string {
  var strCmd = `ML ${h}\n`
  if (rotation == 1) {
    strCmd += 'T90 '
  }
  if (rotation == 2) {
    strCmd += 'T180 '
  }
  if (rotation == 3) {
    strCmd += 'T270 '
  } else {
    strCmd += 'T '
  }
  strCmd += `${fontName} ${fontSize} ${x} ${y}\n${content}\nENDML\n`
  return strCmd
}

/**
 * 打印一维码
 *
 * x: 文字方块左上角X座标，单位dot
 * y: 文字方块左上角Y座标，单位dot
 * codeType: 条码类型，取值为128、UPCA、UPCA2、UPCA5、UPCE、UPCE2、UPC5、EAN13、EAN13+2、EAN13+5、
 *      EAN8、EAN8+2、EAN8+5、39、39C、F39、F39C、93、CODABAR、CODABAR16、ITF、I2OF5
 * h: 条码高度，单位dot
 * rotation: 顺时针旋转角度，取值如下：
 *     - 0 不旋转
 *     - 1 顺时针旋转90度
 *
 * narrow: 窄条码比例因子(dot) 取值： 參考文檔
 * wide: 宽条码比例因子(dot) 取值： 參考文檔
 * content: 文字内容
 *
 */
export function addCPCLBarCode(
  x: number,
  y: number,
  codeType: string,
  h: number,
  rotation: number,
  narrow: number,
  wide: number,
  content: string
): string {
  var strCmd = ''
  if (rotation == 0) strCmd += 'B '
  else strCmd += 'VB '
  strCmd +=
    codeType +
    ' ' +
    narrow +
    ' ' +
    wide +
    ' ' +
    h +
    ' ' +
    x +
    ' ' +
    y +
    ' ' +
    content +
    '\n'
  return strCmd
}

/**
 * 打印二维码
 *
 * x: 文字方块左上角X座标，单位dot
 * y: 文字方块左上角Y座标，单位dot
 * level: 错误纠正能力等级，取值为L(7%)、M(15%)、Q(25%)、H(30%)
 * ver: 1-10 版本，根据内容调整以获取合适容量
 * scale: 1-10 放大倍数
 * content: 文字内容
 *
 */
export function addCPCLQRCode(
  x: number,
  y: number,
  level: string,
  ver: number,
  scale: number,
  content: string
): string {
  var strCmd =
    'B QR ' +
    x +
    ' ' +
    y +
    ' M ' +
    ver +
    ' U ' +
    scale +
    '\n' +
    level +
    'A,' +
    content +
    '\n'
  strCmd += 'ENDQR\n'
  return strCmd
}

/**
 * 放大指令
 * scaleX: 横向放大倍数 1，2，3等整数
 * scaleY: 纵向放大倍数 1，2，3等整数
 */
export function addCPCLSETMAG(scaleX: number, scaleY: number) {
  var strCmd = 'SETMAG ' + scaleX + ' ' + scaleY + '\n'
  return strCmd
}

/**
 * 对齐指令 0-左对齐 1-右对齐 2-居中
 */
export function addCPCLLocation(set?: any) {
  var strCmd = ''
  if (set == 1) {
    strCmd += 'RIGHT\n'
  } else if (set == 2) {
    strCmd += 'CENTER\n'
  } else {
    strCmd += 'LEFT\n'
  }
  return strCmd
}

export function addCPCLBold(level?: any) {
  return `SETBOLE ${level ? 1 : 0}\n`
}

/**
 * 打印指令
 */
export function addCPCLPrint() {
  var strCmd = 'PRINT\n'
  return strCmd
}

/**
 * 图片打印指令
 * x: 文字方块左上角X座标，单位dot
 * y: 文字方块左上角Y座标，单位dot
 * data{
            threshold,//0/1提取的灰度级
            width,//图像宽度
            height,//图像高度
            imageData , //图像数据
    }
 */
/**
 * 将二进制图片数据转换成 CPCL 指令
 * @param x 图片横向位置
 * @param y 图片纵向位置
 * @param data 包含图片的信息，如宽度、高度、阈值等
 * @returns 返回 CPCL 指令
 */
export function addCPCLImageCmd(x: number, y: number, data: {
  threshold?: number;
  width: number;
  height: number;
  imageData: number[];
}): string {
  var strImgCmd = ''
  const threshold = data.threshold || 180
  let myBitmapWidth = data.width,
    myBitmapHeight = data.height
  let len = parseInt((myBitmapWidth + 7) / 8) //一行的数据长度

  let ndata = 0
  let i = 0
  let j = 0
  let sendImageData = new Uint8Array(len * myBitmapHeight)
  let pix = data.imageData

  for (i = 0; i < myBitmapHeight; i++) {
    for (j = 0; j < len; j++) {
      sendImageData[ndata + j] = 0
    }
    for (j = 0; j < myBitmapWidth; j++) {
      const grayPixle1 = grayPixle(
        pix.slice((i * myBitmapWidth + j) * 4, (i * myBitmapWidth + j) * 4 + 3)
      )
      if (grayPixle1 < threshold)
        sendImageData[ndata + parseInt(j / 8)] |= 0x80 >> j % 8
    }
    ndata += len
  }

  //CPCL指令图片数据
  strImgCmd += 'EG ' + len + ' ' + myBitmapHeight + ' ' + x + ' ' + y + ' '
  for (i = 0; i < sendImageData.length; i++) {
    strImgCmd += Hex2Str(sendImageData[i])
  }
  strImgCmd += '\n'

  return strImgCmd
}

